package moe.dao.pool;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Pool<T> {
	private final Lock coreLock;
	private final BlockingQueue<PoolEntity<T>> poolQueue;
	private int coreSize, aliveTimeout, coreTimeout, coreCount = 0;

	Pool(int capacity, int coreSize, int aliveTimeout, int coreTimeout) {
		this.coreSize = coreSize;
		this.aliveTimeout = aliveTimeout;
		this.coreTimeout = coreTimeout;
		poolQueue = new ArrayBlockingQueue<PoolEntity<T>>(capacity);
		coreLock = new ReentrantLock();
	}

	PoolEntity<T> checkout(long timeout, TimeUnit unit) throws InterruptedException {
		PoolEntity<T> entity = poolQueue.poll(timeout, unit);
		if (entity != null) {
			entity.checkout(this);
		}
		return entity;
	}

	void checkin(PoolEntity<T> obj) {
		poolQueue.add(obj);
	}

	boolean isEmpty() {
		return poolQueue.isEmpty();
	}

	boolean intoCore() {
		coreLock.lock();
		try {
			if (coreCount >= coreSize) {
				return false;
			}
			coreCount++;
			return true;
		} finally {
			coreLock.unlock();
		}
	}

	void leaveCore() {
		coreLock.lock();
		try {
			coreCount--;
		} finally {
			coreLock.unlock();
		}
	}

	void clear() {
		PoolEntity<T> entity = null;
		while ((entity = poolQueue.poll()) != null) {
			entity.close();
		}
	}

	int size() {
		return poolQueue.size();
	}

	int getAliveTimeout() {
		return aliveTimeout;
	}

	int getCoreTimeout() {
		return coreTimeout;
	}
}
